package cz.semjob.learning.instances;

import java.util.List;

import org.springframework.stereotype.Component;

import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import cz.semjob.document.annotation.metadata.Relation;
import cz.semjob.learning.data.attribute.AInstanceAttribute;
import cz.semjob.learning.data.attribute.NominalInstanceAttribute;
import cz.semjob.learning.data.attribute.NumericInstanceAttribute;
import cz.semjob.learning.data.attribute.TextDistributionInstanceAttribute;
import cz.semjob.learning.instances.loader.InstancesLoadingException;

@Component
public class WekaInstanceHelper {

	public Instance createWekaInstance(ITextInstance instance,
			Instances wekaDataSet) {
		// Instance wekainstance = new
		// DenseInstance(instance.getAttributesList().size()+1);
		Instance wekainstance = new Instance(instance.getAttributesList()
				.size() + 1);
		wekainstance.setDataset(wekaDataSet);
		int attIndex = 0;
		for (AInstanceAttribute attribute : instance.getAttributesList()) {
			String name = attribute.getName();
			if (instance.getAttributeValues().containsKey(name)) {
				if (attribute instanceof NominalInstanceAttribute) {
					wekainstance.setValue(attIndex, (String) (instance
							.getAttributeValues().get(name)).getAttrValue());
				} else if (attribute instanceof NumericInstanceAttribute) {
					wekainstance.setValue(attIndex, (Double) (instance
							.getAttributeValues().get(name)).getAttrValue());
				} else {
					wekainstance.setMissing(attIndex);
				}
			} else {
				wekainstance.setValue(attIndex, "0");
			}
			attIndex++;
		}
		// wekainstance.setValue(attIndex, 0); // setting class value
		wekaDataSet.add(wekainstance);
		return wekainstance;
	}

	/**
	 * Creates weka attributes info from list of instance attributes.
	 * 
	 * @param attributes
	 * @param positiveClassName
	 * @return
	 * @throws InstancesLoadingException
	 */
	public FastVector getWekaAttributesInfo(
			List<AInstanceAttribute> attributes, String positiveClassName)
			throws InstancesLoadingException {
		FastVector fvAttributes = createFvAttributes(attributes);
		FastVector fvNominalVal = new FastVector(2);
		fvNominalVal.addElement(positiveClassName);
		fvNominalVal.addElement("non-" + positiveClassName);
		Attribute classAttribute = new Attribute("class", fvNominalVal);

		fvAttributes.addElement(classAttribute);
		return fvAttributes;
	}

	public FastVector getWekaAttributesInfo(
			List<AInstanceAttribute> attributes, List<Relation> relations)
			throws InstancesLoadingException {
		FastVector fvAttributes = createFvAttributes(attributes);
		FastVector fvNominalVal = new FastVector(2);
		for (Relation relation : relations) {
			fvNominalVal.addElement(relation.getName());
		}
		Attribute classAttribute = new Attribute("class", fvNominalVal);

		fvAttributes.addElement(classAttribute);
		return fvAttributes;
	}

	private FastVector createFvAttributes(List<AInstanceAttribute> attributes)
			throws InstancesLoadingException {
		FastVector fvAttributes = new FastVector(attributes.size() + 1);
		for (AInstanceAttribute instanceAttribute : attributes) {
			if (instanceAttribute instanceof NominalInstanceAttribute) {
				NominalInstanceAttribute nominalAttribute = (NominalInstanceAttribute) instanceAttribute;
				FastVector fvNominalVal = new FastVector(
						nominalAttribute.getValues().length + 1);
				for (String string : nominalAttribute.getValues()) {
					fvNominalVal.addElement(string);
				}
				fvNominalVal.addElement("0");
				Attribute attribute = new Attribute(nominalAttribute.getName(),
						fvNominalVal);
				fvAttributes.addElement(attribute);
			} else if (instanceAttribute instanceof NumericInstanceAttribute) {
				Attribute attribute = new Attribute(instanceAttribute.getName());
				fvAttributes.addElement(attribute);
			} else if (instanceAttribute instanceof TextDistributionInstanceAttribute) {
				Attribute attribute = new Attribute(instanceAttribute.getName());
				fvAttributes.addElement(attribute);
			} else {
				throw new InstancesLoadingException(
						"Unknown attribute type, only nominal and numeric are supported");
			}
		}
		return fvAttributes;
	}

}
